<?php

	include_once("cmsConfig.php");
	include_once("CmsStatusMessage.php");
	include_once("imagesModule.php");
	
	/**
		class to provide cms write/update functionality
	*/
	

	class CmsWriter {
				

		var $formId;
		var $documentCode;
		var $formData;
		var $authInfo;
		var $db;
		
		//table writers - lazy loaded as needed//
		var $contentTableWriter;
		var $cmscontentmetadataTableWriter;
		var $imageTableWriter;
		var $manyToManyTableWriter;
		var $binaryDataTableWriter;
		var $formDescriptorTableWriter;
		var $movieDescriptorTableWriter;
		var $siteContentTableWriter;
		var $multipleKeyWriter;


		function CmsWriter( $formId, $documentCode, $formData, &$authInfo, &$db) {
			$this->formId = $formId;
			$this->documentCode = $documentCode;
			$this->formData = $formData;
			$this->authInfo  = $authInfo;
			$this->db = &$db;
		}

		
		function &getCmsContentMetaDataTableWriter() {
			if (!isset($this->cmscontentmetadataTableWriter)) {
				$this->cmscontentmetadataTableWriter = new CmsTableWriter("cmscontentmetadata", $this->db);
			}
			return $this->cmscontentmetadataTableWriter;
		}
		
		function &getContentTableWriter(){
			if ( !isset($this->tableWriter)){
				$this->contentTableWriter = new CmsTableWriter(CMS_FORMAT, $this->db);
			}
			return $this->contentTableWriter;
		}
			
	
		function &getImageTableWriter() {
			if (! isset($this->imageTableWriter) ){
				$this->imageTableWriter = new CmsTableWriter(CMS_IMAGE_DESCRIPTOR ,$this->db);
			}
			return $this->imageTableWriter;
		}
		
		function &getManyToManyTableWriter() {
			if (! isset($this->manyToManyTableWriter)){
				$this->manyToManyTableWriter = new CmsTableWriter(CMS_MANYDATA, $this->db);
			}
			return $this->manyToManyTableWriter;
		}
		
		function &getMultipleKeyWriter() {
			if (! isset($this->multipleKeyWriter)){
				$this->multipleKeyWriter = new CmsTableWriter(CMS_MULTIPLEKEYVALUE, $this->db);
			}
			return $this->multipleKeyWriter;
		}
		
		function &getBinaryDataTableWriter() {
			if(! isset( $this->binaryDataTableWriter)){
				$this->binaryDataTableWriter = new CmsTableWriter(CMS_BINARYDATA, $this->db);
			}
			return $this->binaryDataTableWriter;
		}
	
		function &getFormDescriptorTableWriter() {
			if(! isset( $this->formDescriptorTableWriter)){
				$this->formDescriptorTableWriter = new CmsTableWriter(CMS_FORM_DESC_FORMAT, $this->db);
			}
			return $this->formDescriptorTableWriter;
		}
		
		function &getMovieDescriptorTableWriter() {
			if (!isset($this->movieDescriptorTableWriter)) {
				$this->movieDescriptorTableWriter = new CmsTableWriter(CMS_MOVIE_DESCRIPTOR, $this->db);
			}
			return $this->movieDescriptorTableWriter;
		}
		
		function &getCascadingDeletesTableWriter() {
			if (!isset($this->cascadingDeletesTableWriter)) {
				$this->cascadingDeletesTableWriter = new CmsTableWriter("cascadingdeletes", $this->db);
			}
			return $this->cascadingDeletesTableWriter;
		}
		
		function &getSearchKeyWordTableWriter() {
			if (!isset($this->searchKeyWordTableWriter)) {
				$this->searchKeyWordTableWriter = new CmsTableWriter("searchkeyword", $this->db);
			}
			return $this->searchKeyWordTableWriter;
		}
		
		function getContentTableWriterExtra() {
			if (!isset($this->extraContentTableWriter)) {
				$this->extraContentTableWriter = new CmsTableWriter(CMS_FORMAT, $this->db);
			}
			return $this->extraContentTableWriter;
		}
		
		function getSiteContentTableWriter(){
			if (!isset($this->siteContentTableWriter)){
				$this->siteContentTableWriter = new CmsTableWriter("sitecontent", $this->db);
			}
			return $this->siteContentTableWriter;
		}
		
		function deleteItem() {
			if ($this->documentCode) {
				$this->cmsDeleteRecord();
			}
		}
		
		
		
		function deleteRecord($documentCode = null, $message = null) {
			
			if (is_null($documentCode)) {
				$documentCode = $this->documentCode;
			}
			
			$tableWriter = $this->getContentTableWriter();
			$formDescriptior = $this->getFormDescriptorTableWriter();
			$authInfo = $this->authInfo;
			$db = $this->db;
			$cascadingdeletes = $this->getCascadingDeletesTableWriter();
			$binaryTableWriter = $this->getBinaryDataTableWriter();
			$manytomanyTableWriter = $this->getManyToManyTableWriter();
			$searchkeywordTableWriter = $this->getSearchKeyWordTableWriter();
			$extraTableWriter = $this->getContentTableWriterExtra();
			
			
			if (($documentContent = $tableWriter->readItem($documentCode)) &&
				($formDescription = $formDescriptior->readItem($documentContent->formid)) &&
				(deleteFormAuth($authInfo,$formDescription, $documentCode, $db))) {
					
				//find the documenttypecode
				$docType = $documentContent->documenttypecode;
				
				//Check to see if there are any related document types
				$relatedmessage = "";				
				$rows = $cascadingdeletes->resetCustomIterator("Where documenttypecode='$docType'");
				if(count($rows) > 0) {
					//if there are any rows delete the corresponding items
					while($row = $cascadingdeletes->nextItem()) {
						$relateddocType = $row->relateddocumenttypecode;
						$relatedfield = $row->relatedfield;
						$relatedtable = $row->relatedtable;						
						$extrarows = $extraTableWriter->resetCustomIterator("WHERE documenttypecode='".$relateddocType."' AND ".$relatedfield."=".$documentCode);
						//if there are any actual records delete them
						if(count($extrarows) > 0) {
							while($extrarows = $extraTableWriter->nextItem()) {
								$relateddocumentcode = $extrarows->documentcode;
								$message .= $this->deleteRecord($relateddocumentcode, $message);
							}
						}
					}
				}
				
				//delete any related items from the binarydata table
				$binaryDelete = $binaryTableWriter->resetCustomIterator("WHERE documentcode=".$documentCode);
				$relatedmessage .= clearItemsFromCacheWithDocumentCode($documentCode, CMS_BINARY_CACHE_PATH) . " cached items removed.<br />";
				if (count($binaryDelete) > 0) {
					while ($binaryDelete = $binaryTableWriter->nextItem()) {
						$binaryCode = $binaryDelete->id;
						if ($binaryTableWriter->deleteItem($binaryCode)) {
							$relatedmessage .= "Related Binary Data Deleted<br />";
						} else {
							$relatedmessage .= "Failed to Delete Related Binary Data<br />";
						}
					}
				}
				
				//delete any related items from the manytomany table
				$manytomanyDelete = $manytomanyTableWriter->resetCustomIterator("WHERE parentcode=".$documentCode);
				if (count($manytomanyDelete) > 0) {
					while ($manytomanyDelete = $manytomanyTableWriter->nextItem()) {
						$manytomanyCode = $manytomanyDelete->manytomanycode;
						if ($manytomanyTableWriter->deleteItem($manytomanyCode)) {
							$relatedmessage .= "Related Manytomany Data Deleted<br />";
						} else {
							$relatedmessage .= "Failed to Delete Related Manytomany Data<br />";
						}
					}
				}
				//delete any related items from the manytomany table
				$manytomanyDelete = $manytomanyTableWriter->resetCustomIterator("WHERE relatedcode=".$documentCode);
				if (count($manytomanyDelete) > 0) {
					while ($manytomanyDelete = $manytomanyTableWriter->nextItem()) {
						$manytomanyCode = $manytomanyDelete->manytomanycode;
						if ($manytomanyTableWriter->deleteItem($manytomanyCode)) {
							$relatedmessage .= "Related Manytomany Data Deleted<br />";
						} else {
							$relatedmessage .= "Failed to Delete Related Manytomany Data<br />";
						}
					}
				}				
					
				if ($tableWriter->deleteItem($documentCode)){
					$message = "The content item was sucessfully deleted from the CMS.";
					$message .= "<br/>". $relatedmessage;
				} else {
					$message = "Failed to delete the content item from the CMS.";
					$message .= "<br/>". $relatedmessage;
				}
				//flush the keywords..
				$db->executeQuery("DELETE FROM searchkeyword WHERE documentcode='" .$documentCode . "'" );
				
				//delete the cmscontentmetadata
				$db->executeQuery("DELETE FROM cmscontentmetadata WHERE documentcode='".$documentCode."'");
				
				//delete the sitecontent stuff..
				$db->executeQuery("DELETE FROM sitecontent WHERE documentcode='" .$documentCode ."'");
				
			} else {
				$message = "I'm sorry dave, I can't do that.";
			}
			return $message;
		}
		
		
		function processFormData() {

			$cmsStatusMessage = new CmsStatusMessage();
			
			 
			$contentTableWriter = $this->getContentTableWriter();//fucking naff
			$cmscontentmetadataTableWriter = $this->getCmsContentMetaDataTableWriter();
			$formDescriptorTableWriter = $this->getFormDescriptorTableWriter();
			$movieDescriptorTableWriter = $this->getMovieDescriptorTableWriter();
			$siteContentTableWriter = $this->getSiteContentTableWriter();
			
						
			//more than likely we need to shift this elsewhere.. up to the save point
			$newDocument = false;
			if ( is_null( $this->documentCode ) ) {
				$newDocument = true;
				$this->documentCode = $this->db->getId('contenttablesequence');
			}
			
			//embed in the document code that has been passed in to us.. not something that comes in
			// on the form data
			$this->formData['documentcode' ] = $this->documentCode;
		
			$formDescription = $formDescriptorTableWriter->readItem($this->formId);
			
			$element = new CmsFormElement($formDescription, $this->db);
			$document = null;
						
			if ($newDocument){
				// we may need to hack shit in here.. be we want to avoid it.									
				if (!addFormAuth($this->authInfo, $formDescription, null, $this->db)) { 					
					$cmsStatusMessage->addValidationMessageForKey('Content','f_PERM_NO_ADD',CMS_STATUS_ERROR);
					return $cmsStatusMessage;
				}
				
			} else {
			
				//other wise.. we need to try and load the content..
				// and merge it..
				$content =  $contentTableWriter->readItem( $this->documentCode );
				$cmscontentmetadata = $cmscontentmetadataTableWriter->readItem( $this->documentCode );
				if (!is_null( $content )){
					$element->setContent( $content );
					$formDescription = $formDescriptorTableWriter->readItem($content->formid);
				}
				
				if (!editFormAuth($this->authInfo, $formDescription, $content->documentcode, $this->db)) {
					//add a message and barf out early..
					$cmsStatusMessage->addValidationMessageForKey('Content','f_PERM_NO_EDIT',CMS_STATUS_ERROR);
					return $cmsStatusMessage;
				}
				
			}
			
		//	myPrintR($this->formData);
			
		//	$cmsStatusMessage->hasErrors = true;
		//	return $cmsStatusMessage;
			

			// turn transactions/on/off here.. all db up to this point is read only.. after here writes will happen..
			if (CMS_WRITER_ENABLE_TRANSACTIONS ){
				//set the autocommit on the db..
				$this->db->setAutoCommit( false );
			}
						
			//can i move this here..
			$contentTableWriter->begin();

			$formGid = $formDescription->gid;
			$formUid = $formDescription->uid;
			$formPermission = $formDescription->permission;
			
			//remove records from the formdescriptor that
			//are not data fields. this should be moved.
			unset($formDescription->formid);
			unset($formDescription->formname);
			unset($formDescription->usertype);
			unset($formDescription->editmode);
			unset($formDescription->uid);
			unset($formDescription->gid);
			unset($formDescription->permission);
			unset($formDescription->sidebarmodule);
			unset($formDescription->activemodule);
			unset($formDescription->contentmodule);
			unset($formDescription->modeaccess);
//			
			//things that we need to declare for later
			$checkBoxList  = array();
			$multipleKeyValuesK = array();
			$multipleKeyValuesV = array();
			$hasMKVP = false;
			
//			myPrintR( $formDescription) ;
			foreach ($formDescription as $formElement){
			
			
				//get the element that we are using.
				$e = $element->getElementDescriptor($formElement);			

				
				// assumptions made here..
				// 1.  all elements with an element type of 0/_BLANK will be dropped

				if ( isset($e) && $e->elementid != 0 && $e->elementtype != CMS_ELEMENT_HIDDEN && $e->elementtype !=CMS_ELEMENT_UNPARSED_TEXT_LABEL ){


					// we pull the form data out and set it back to ensure that 
					// there is a record in the form data, and the key is set regardless.
					 $data = extractValueWithKeyFromArray($e->name, $this->formData, null);//evil munge to sort out the field

//*****Need to	   //if (is_string($data) && strlen($data) == 0  )
//redo this somehow		//	$data = null;
//but keep it a string as otherwise you can't save it if it's empty					 	

					 $this->formData[ $e->name ] = $data;
					 
	
					//m-m options..
					if ($e->elementtype == CMS_ELEMENT_CHECKBOX_LIST || 
						$e->elementtype == CMS_ELEMENT_IMPROVED_CHECKBOX_LIST
						 ){//are there other types of cms m-m elements?
						if(isset($this->formData[ $e->name ])){
							$checkBoxList[$e->elementid] = $this->formData[  $e->name ];
						}
					}
			
					
					
				// the behaviour of checkboxes has been altered as now we are using the js version
				// that give us an on off value..
				//	//checkboxes.. need to be set.
					if ($e->elementtype == CMS_ELEMENT_CHECKBOX) {
					
						if ( $this->formData[ $e->name ] )
							$this->formData[ $e->name ] = 1;
						else
							$this->formData[ $e->name ] = 0;
					}
					
					//things we dont default.. or cant

					switch ($e->elementtype){
						//these fields cant have a default.
						case CMS_ELEMENT_FILE_UPLOAD:
						case CMS_ELEMENT_HIDDEN:
						break;

						
						// these are elements.. that update to their default every time
						// that the document is saved.
						// therefore we remove the content.. and fall thorugh 
						// to the normal defaulting mechanism.
						case CMS_ELEMENT_UPDATING_LABEL:
							unset($element->content->{ $e->name });
//						break;

						// these are defaults that cannot be changed
						// once they have been saved ie: write once.
						// the rest of the time we use the existing content
						case CMS_ELEMENT_UPDATING_VALUE_LABEL:
						case CMS_ELEMENT_LABEL:// these are considered a write once label
						case CMS_ELEMENT_HIDDEN_WITH_LABEL:
							// labels and hiddens..
							// all take the default etc.. always..
							// this way the value will never change.
							$this->formData[ $e->name ] = $element->getDefault($e);
						break;
						
						case CMS_ELEMENT_KVCID:
							//this we check to see if we have one.. if we do then cool..
							// otherwise.. we need to generate one..
							//;
							if (is_null($this->formData[ $e->name ])) {
								//try for a default
								$this->formData[ $e->name] = $element->getDefault($e);
								//if still nothing.. make one up..
								if(is_null($this->formData[ $e->name ]))
									$this->formData[ $e->name ] = substr(md5(uniqid(rand(), true)),rand(0,21),8);//trufle shuffle..
							}
						break;
						
						// we add this here.. as we can then bolt the pk in, in a more
						// sensible fashion.
						case CMS_ELEMENT_PRIMARY_KEY:
							//basically, we just take what is in the form data..
							// and if nothing is here.. then we .. throw a hissey later?
							//$this->formData[$e->name] =;
							
						break;
						
						case CMS_ELEMENT_MULIPLE_KEY_VALUE_PAIRS:
							// this is a form element that will write multiple key value pairts
							// to the database..
							//as there are multiple values.. we handle it much like 
							//the many to many data..
							//first the keys..
							$hasMKVP = true;
							if( isset( $this->formData[ 'kvp_key_' . $e->elementid ])){
								$multipleKeyValuesK[$e->elementid] = $this->formData[  'kvp_key_' . $e->elementid  ];
							}

							if( isset( $this->formData[ 'kvp_value_' . $e->elementid ])){
								$multipleKeyValuesV[$e->elementid] = $this->formData[  'kvp_value_' . $e->elementid  ];
							}	
						break;
						
						// these are for things that will, be defaulted..only
						// if the doucment is a new document.. otherwise, it
						// will just use the post value. 

						default:

							//need a content bubble to write values to..
							if ( !isset($element->content))
								$element->content = new stdClass();

							$element->content->{ $e->name } = $this->formData[ $e->name ];	

//****** Need to redo this somehow but keep it as a string because otherwise you can't save it if it's empty
							//$this->formData[ $e->name ] = $element->getDefault($e);
							
								

						break;
					}


					if (($val =$element->validateElement($contentTableWriter->getFieldInfo($e->name), $this->formData[  $e->name ])) === false) {
						// add message and jump to the top of the loop
						$cmsStatusMessage->addValidationMessageForKey($e->name, "f_NOT_VALID", CMS_STATUS_ERROR);
						continue;
					} else {
						$this->formData[  $e->name ] = $val; 
					}


					if ( ($e->requiredfield) ){

						//check.. if we are a file.. we need to check in the files array.. otherwise the form elements..
						
						if ($e->elementtype == CMS_ELEMENT_FILE_UPLOAD) {
							$_a = &$_FILES;
						} else {
							$_a = &$this->formData;
						}
						
						if (!isset($_a[$e->name]) || is_null( $_a[  $e->name ])) {
							$cmsStatusMessage->addValidationMessageForKey($e->name, "f_NOT_NULL", CMS_STATUS_ERROR);
						}
						
					} 			
					
	
					
					//handle other forms as needed
					$res = false;
					switch ($e->elementtype) {
						case CMS_ELEMENT_FILE_UPLOAD:


							if (!isset($this->formData[  $e->name ]) || 
							(is_string($this->formData[  $e->name ]) && $this->formData[  $e->name ] == ',,') ) {
								$this->formData[  $e->name ] = false;
							}
							
							if (
								key_exists($e->name, $_FILES) &&
								(key_exists($e->name, $_FILES) &&
								key_exists('tmp_name', $_FILES[$e->name]) && 
								is_uploaded_file ($_FILES[$e->name]['tmp_name']) )
								||
								$this->formData[  $e->name ]
							) {		
								//
								$binaryFiles[$e->name] = $e->elementid;
								//Make an array of files that need saving
								if(!isset($binaryFiles) || !is_array($binaryFiles)) {
									$binaryFiles = array();
								}
								
								
								if ( is_uploaded_file( $_FILES[$e->name]['tmp_name'])) {
									//do nothing here..
								} else if (is_string($this->formData[  $e->name ]) && strlen($this->formData[  $e->name ]) > 0) {
									
									$binaryBits = explode(",",$this->formData[  $e->name ]);
									if (count($binaryBits)==3){
										//value="$binaryDocumentCode,$binaryFileId,$binaryElementId"//
										$query = "SELECT * FROM binarydata WHERE documentcode=$binaryBits[0] AND id=$binaryBits[1] AND elementid=$binaryBits[2] AND filetypecode=1";
										$this->db->executeQuery($query);
										if ($row = $this->db->nextObject()){
									
											
											$_FILES[$e->name]['name'] = $row->filename;
											$_FILES[$e->name]['type'] = $row->mimetype;
											$_FILES[$e->name]['size'] = $row->filesize;
											$_FILES[$e->name]['tmp_name'] = null; // i am the evil variable maker skull duggery <content>
											$_FILES[$e->name]['data'] = array($row->content);
											
										} else {
											//somnething went wrong.. throw a dirty validation type error here..
											$cmsStatusMessage->addValidationMessageForKey($e->name, "f_BINARY_COPY_LOOKUP_ERROR", CMS_STATUS_ERROR);
										}
									}
								}
							}
						break;
						
						case CMS_ELEMENT_CHECKBOX_LIST:
						case CMS_ELEMENT_IMPROVED_CHECKBOX_LIST:
						case CMS_ELEMENT_MULIPLE_KEY_VALUE_PAIRS:
							$contentTableWriter->addField($e->name, $formElement);
						break;
						
						default:
							$contentTableWriter->addField($e->name,  makeTextSafe( $this->formData[  $e->name ] ));//echo $e->name . " = " . makeTextSafe($this->formData[$e->name]) . "<br />";
						break;
					}
					
					
				}
			}
			

			$result = false;
			
			//just in case..
			$contentTableWriter->addField( 'formid', $this->formId );
			$contentTableWriter->addField( 'documentcode', $this->documentCode );
			
			// this handles the permission details..
			if (!$cmsStatusMessage->hasErrors) {
				if( $newDocument) {
				
					// new items wont have a document code.. add it here
					//$contentTableWriter->addField( 'documentcode', $this->documentcode);//
					// only save the uid if we are adding.. dont want to change this to the editor..
					$contentTableWriter->addField('uid', $this->authInfo->uid);
					
					// we need to see if we have been passed in a gid..
					// and if we have.. check that the user is in that group..
					// if not throw an hissey//
					
					// if we have no gid.. use the view mode gid					
					$gid = extractNumberWithKeyFromArray('gid', $this->formData, null);
					
					if ( is_null($gid)) {
						
						//how do we get a default user gid??????
						//$contentTableWriter->addField('gid', $this->authInfo->uid);
						// use the forms..
						//$contentTableWriter->addField('gid', $formGid);
						
						// we change this. if there is no gid.. we need to look up 
						// from the current view mode..
						// and use that as the base permission.
						
						$viewMode =  extractNumberWithKeyFromArray('viewMode',$_SESSION, null);
						
						if (is_null($viewMode)) {
							//this should really never happen..
							$gid =$formGid;
						} else {
							$gid = groupForMode($viewMode, $this->db);
						}
						
						//$gid =$formGid;
						
					}
					
					$contentTableWriter->addField('gid', $gid);
					
					$permissions = extractNumberWithKeyFromArray( 'permissions', $_REQUEST, null);
					if (!is_null($permissions)) {
						//add optional checks here to ensure that the user can set permissions
						// currently we can just take the parents/form permissions..
					} else {
						$contentTableWriter->addField('permissions', $formPermission);						
					}
					
					if ( !$cmsStatusMessage->hasErrors ) {
						$result = $contentTableWriter->newItem();
					}
					
				} else {
					//existing items.. should have a dcoument code already
					//echo "<pre>";print_r($contentTableWriter);echo "</pre>";
					$result = $contentTableWriter->saveItem();
				}
			}
			
			clearItemsFromCacheWithDocumentCode($this->documentCode, CMS_BINARY_CACHE_PATH);

		
			//meta data stuff..
			$metadata_label = extractStringWithKeyFromArray("metadata_label", $_REQUEST, null);
			$metadata_rank = extractNumberWithKeyFromArray("metadata_rank", $_REQUEST, null);
			if (!isset($gid) || !$gid) {
				$gid = extractNumberWithKeyFromArray("gid", $_REQUEST, null);
				if (!$gid && isset($content->gid)) {
					$gid = $content->gid;
				}
			}
			
			//permissions fangling on the meta data
			if (!isset($uid) || !$uid) {
				$uid = extractNumberWithKeyFromArray("uid", $_REQUEST, null);
				if (!$uid && isset($content->uid) && $content->uid) {
					$uid = $content->uid;
				}
				if (!$uid) {
					$uid = $this->authInfo->uid;
				}
			}
			
			if (!isset($permissions) || !$permissions) {
				$permissions = extractNumberWithKeyFromArray("uid", $_REQUEST, null);
				if (!$permissions && isset($content->permissions)) {
					$permissions = $content->permissions;
				}
			}
			//write the metadata..
			$cmscontentmetadataTableWriter->begin();
			$cmscontentmetadataTableWriter->addField("documentcode", $this->documentCode);
			$cmscontentmetadataTableWriter->addField("label", $metadata_label);
			$cmscontentmetadataTableWriter->addField("rank", $metadata_rank);
			$cmscontentmetadataTableWriter->addField("uid", $uid);
			$cmscontentmetadataTableWriter->addField("gid", $gid);
			$cmscontentmetadataTableWriter->addField("permissions", $permissions);
			
			if (isset($cmscontentmetadata->documentcode) && $cmscontentmetadata->documentcode) {
				$cmscontentmetadataTableWriter->saveItem();
			} else {
				$cmscontentmetadataTableWriter->newItem();
			}
			

			
			//sitecontent fangling goes here..
			//this may be a little tricky..
			// we need to here.. get the sites.. and do all sorts of silly tests and crap
			
//			$userSites =;
//			$contentSites =;
// mangle an then set..
			
			if (CMS_ENABLE_SITE_CONTENT) {
				
				$siteContentTableWriter = $this->getSiteContentTableWriter();
				
				$userSitesObjects = getSiteModesForUser($this->authInfo->uid, $this->db);
				//we need to thin the user sites...
				$userSites = array();
				foreach( $userSitesObjects as $userSite){
					array_push($userSites, $userSite->gid);
				}				

				($documentCodeArray = array($this->documentCode));
				$allContentSitesObjects = $this->db->getAllAsObjects("SELECT gid FROM grouplist AS t1,sitecontent AS t2 WHERE t1.gid = t2.sitegroupid AND t2.documentcode=?", $documentCodeArray );	
				
				
				$allContentSites = array();
				foreach( $allContentSitesObjects as $aContentSite){
					array_push($allContentSites, $aContentSite->gid);
				}
				
				
				//now we can remove 	
				
				if(!$newDocument) {
					$siteContentTableWriter->resetCustomIterator("WHERE documentcode='".$this->documentCode."' ");
					while($siteContentItem = $siteContentTableWriter->nextItem() ) {
						$siteContentTableWriter->deleteItem($siteContentItem->id);
					}
				}
			
						
				$sitesFromRequest = extractArrayWithKeyFromArray("sites", $_REQUEST, ($a =array()) );
//				myPrintR($sitesFromRequest, "sitesFromRequest");
//
				// now we need to ensure that those that were originally removed that the user does not have permission to edit are added back in..
				// this is the set of sites that are not user sites.. but in the actual original content.
				$sitesFromContentThatCantBeRemoved = array_diff($allContentSites, $userSites );
				//myPrintR($sitesFromContentThatCantBeRemoved,"sitesFromContentThatCantBeRemoved");
				
				//this is the set of sites that came in on the request.. but only those.. that the user has permission to access
				$permittedSitesToAdd = array_intersect($userSites, $sitesFromRequest);
				//myPrintR($permittedSitesToAdd,"permittedSitesToAdd");
				
				
				//do the write..
				$sitesToSave = array_merge($sitesFromContentThatCantBeRemoved, $permittedSitesToAdd);
				//myPrintR($sitesToSave,"sitesToSave");
				
				foreach ($sitesToSave as $aSite){
					$newId = $siteContentTableWriter->db->getId('sitecontentsequence');
					$siteContentTableWriter->begin();
					$siteContentTableWriter->addField('id',$newId);
					$siteContentTableWriter->addField("documentcode", $this->documentCode);
					$siteContentTableWriter->addField("sitegroupid", $aSite);
					$siteContentTableWriter->newItem();					
				}
				
				
			}

						
			//
			//
			//many to many fangling
			if (!$result) {
				$cmsStatusMessage->addValidationMessageForKey("CmsWrite", "db_QUERY_ERROR", CMS_STATUS_ERROR);
			} else {
			
			///
				// if saving the changes worked 
				// then we can do other shit like set up the many to many 
				// save / update many to many
				$manyToManyTableWriter = $this->getManyToManyTableWriter();
				
				//We have to remove all the many to many's before adding them again.
				//Generate an array of all the document codes to be deleted and delete them
				if(!$newDocument) {
					$manyToManyTableWriter->resetCustomIterator("Where parentcode='".$this->documentCode."' ");
					while($rowMtoM = $manyToManyTableWriter->nextItem() ) {
						$manyToManyTableWriter->deleteItem($rowMtoM->manytomanycode);
					}
				}
				
				//save the many to many items.
				//Loop through the $checkBoxList saving the options as we go
				if (is_array($checkBoxList)) {
					foreach($checkBoxList as $key=>$value ) {
						if(isset($value)) {
							foreach($value as $v) {
								$newId = $manyToManyTableWriter->db->getId('manytomanydatatablesequence');
								
								$manyToManyTableWriter->begin();
								$manyToManyTableWriter->addField("manytomanycode", $newId);
								$manyToManyTableWriter->addField("parentcode", $this->documentCode);
								$manyToManyTableWriter->addField("relatedcode", $v);
								$manyToManyTableWriter->addField("elementid", $key);
								$manyToManyTableWriter->newItem();
							}
						}
					}
				}
				///
				$multipleKeyWriter = null;
				if ( $hasMKVP )
					$multipleKeyWriter = $this->getMultipleKeyWriter();
				
				if(!$newDocument && $hasMKVP) {
					$multipleKeyWriter->resetCustomIterator(" WHERE documentcode='".$this->documentCode."' ");
					while($rowMK = $multipleKeyWriter->nextItem() ) {
						$multipleKeyWriter->deleteItem($rowMK->id);
					}
				}
				
				if (is_array($multipleKeyValuesK) && $hasMKVP ) {
						foreach ($multipleKeyValuesK as $i => $mkKeys ){
							$mkValues =  $multipleKeyValuesV[ $i ];
							
							foreach ($mkKeys as $j => $keyValue) {

								$keyValue = extractStringWithKeyFromArray($j,$mkKeys,"");
								$value = extractStringWithKeyFromArray($j, $mkValues, "");

									
								$newId = $multipleKeyWriter->db->getId('multiplekeyvaluepairsequence');
								$multipleKeyWriter->begin();
								$multipleKeyWriter->addField("id", $newId);
								$multipleKeyWriter->addField("documentcode", $this->documentCode);
								$multipleKeyWriter->addField("key", $keyValue);
								$multipleKeyWriter->addField("value", $value);
								$multipleKeyWriter->newItem();
								
							}
						}					
				}
					
				//save the images..
				if(isset($binaryFiles) && is_array($binaryFiles)) {
					$binarydata = $this->getBinaryDataTableWriter();
					
					foreach ($binaryFiles as $key=>$value) {	
						//Must loop through and save each file in the form.
						//Must get $e->elementid and $e->name
						
						$data = "";
						$tmpName = $_FILES[$key]["tmp_name"];
						$fileName =  null;
						
						if (is_uploaded_file($tmpName)){
						
							$originalFileName = $_FILES[$key]["name"];
							$fileExtArr = explode(".", $originalFileName);
							krsort($fileExtArr);
							$fileExt = current($fileExtArr);
							$fileName = $tmpName.".".$fileExt;
							$ret = move_uploaded_file($tmpName, $fileName);
						}
						
						if(  is_string($fileName) && strlen($fileName) > 0 && file_exists($fileName) && $ret ) {
						
							// first we need to move the file to where we can fuck around with it.. like
							// the blobcache??
							//move the file name 
							//move_uploaded_file($fileName, CMS_BINARY_CACHE_PATH . )
							//chmod($fileName, 0644);//this is really really really bad news.. as a file is now readable by all .. 
							//change the group to the mysql group??
							//chgrp($fileName, "mysql");

									
							$data = "<< load_file(\"$fileName\") >>";
							//$data = "<< file:$fileName >>";
						} else if ( $fileName === null && is_array($_FILES[$key]['data']) && count($_FILES[$key]['data']) == 1) {
							// we must have a file copy. check for that..//
							$data = &$_FILES[$key]['data'][0];							
						}
						//
						
						// do something else if we have a mem://						
						
						
						// do the rest of the stuff...
						$binarydata->begin();
						
						// how to tell if we are doing.. a file copy or a file
						$binarydata->addField( "content", $data );
						
						$binarydata->addField( "filename", $_FILES[$key]['name']);
						$binarydata->addField( "mimetype", $_FILES[$key]['type']);
						$binarydata->addField( "filesize", $_FILES[$key]['size']);
						$binarydata->addField( "filetypecode", 1);
						$binarydata->addField( "elementid", $value);
						$binarydata->addField( "documentcode", $this->documentCode);
						
						if (!$newDocument) {					
							$binarydata->resetCustomIterator("WHERE filetypecode='1' AND elementid='".$value."' AND documentcode='".$this->documentCode."' ");
							$binaryUpdate = ($binaryRow = $binarydata->nextItem()) ? true : false ;
						} else {
							$binaryUpdate = false;
						}
						
						if($binaryUpdate) {
											
							$fileId = $binaryRow->id;
							$binarydata->addField("id", $fileId);
							
							if (file_exists($fileName))
								chmod($fileName, 0644);// bad news.. 

							$binarydata->saveItem();
							
							if (file_exists($fileName))
								chmod($fileName, 0600);// bad news..
							
						} else {
							
							//if it is a new entry create the new document codes and add to record
							$fileId = $binarydata->db->getId('binarydatatablesequence');
							$binarydata->addField("id", $fileId);
							//write the record.
							if (file_exists($fileName))
								chmod($fileName, 0644);// bad news.. 
							
							$binarydata->newItem();
							
							if (file_exists($fileName))
								chmod($fileName, 0600);// bad news.. 
								
//							$query = "Update content set ".$key."=".$fileId." Where documentcode=".$this->documentCode." ";							
							
							$query = "UPDATE content SET ! = ? WHERE documentcode=?";
							$values = array ( $key, $fileId, $this->documentCode);											
							$this->db->prepareAndExecuteQuery($query,$values );

						}
						
						
						if ($contentDoc = $this->contentTableWriter->readItem($this->documentCode)) {
						
							//Check if Movie Descriptor Record and Process
							$documenttypecode = $contentDoc->documenttypecode;							
							$this->movieDescriptorTableWriter->resetCustomIterator(" WHERE documenttypecode='".$documenttypecode."' AND elementid='".$value."'");
							
							$started = false;
							
							while ($movieDesc = $this->movieDescriptorTableWriter->nextItem()) {
								
								//echo "moviedesc exists<br>";
								$removeFile = true;
								
								//If First Row - Write file to disk for processing
								if (!$started) {						
								}
								
								//Convert file to FLV - write to tmp dir - ready to write to db
								$thisFileName = $this->documentCode."-".$value."-".$movieDesc->filetype.".flv";
								
								//Start Command and Set input file
								$cmd = FFMPEG_PATH."ffmpeg -i ".$fileName;

								//Check options in Movie Descriptor and add to command
								if ($movieDesc->bitrate_kb) {
									$cmd .= " -b ".$movieDesc->bitrate_kb;
								}
								
								if ($movieDesc->framespersecond) {
									$cmd .= " -r ".$movieDesc->framespersecond;
								}
								
								if ($movieDesc->size) {
									$cmd .= " -s ".$movieDesc->size;
								}
								
								if ($movieDesc->aspectratio) {
									$cmd .= " -aspect ".$movieDesc->aspectratio;
								}
								
								if ($movieDesc->paddingtop) {
									$cmd .= " -padtop ".$movieDesc->paddingtop;
								}
								
								if ($movieDesc->paddingbottom) {
									$cmd .= " -padbottom ".$movieDesc->paddingbottom;
								}
								
								if ($movieDesc->paddingleft) {
									$cmd .= " -padleft ".$movieDesc->paddingleft;
								}
								
								if ($movieDesc->paddingright) {
									$cmd .= " -padright ".$movieDesc->paddingright;
								}
								
								if ($movieDesc->paddingcolor_hex) {
									$cmd .= " -padcolor ".$movieDesc->paddingcolor_hex;
								}
								
								if ($movieDesc->buffersize_bits) {
									$cmd .= " -bufsize ".$movieDesc->buffersize_bits;
								}
								
								if ($movieDesc->audiofrequency_hz) {
									$cmd .= " -ar ".$movieDesc->audiofrequency_hz;
								}
								
								if ($movieDesc->audiobitrate_kb) {
									$cmd .= " -ab ".$movieDesc->audiobitrate_kb;
								}
								
								if ($movieDesc->audiochannels) {
									$cmd .= " -ac ".$movieDesc->audiochannels;
								}
								
								//End command with new file path
								$cmd .= " ".CMS_TMP_DIR . $thisFileName;
								
								//echo $cmd;
								
								//$process = proc_open($cmd, $descriptorspec, $pipes);
								//$returnValue = proc_close($process);
								header("X-I-HAS_a-MOVIE-will_COnvert4u: $cmd");
								
								$ret = exec($cmd);
								
								//Grab file and put in variable ready for writing to DB
								$filesize = filesize(CMS_TMP_DIR.$thisFileName);
															
								//Write file to DB
								$binarydata->begin();
								$binarydata->addField( "content", "<< load_file(\"" . CMS_TMP_DIR.$thisFileName . "\") >>" );
								$binarydata->addField( "filename", $thisFileName);
								$binarydata->addField( "mimetype", "video/x-flv");
								$binarydata->addField( "filesize", $filesize);
								$binarydata->addField( "filetypecode", $movieDesc->filetype);
								$binarydata->addField( "elementid", $value);
								$binarydata->addField( "documentcode", $this->documentCode);
								
								if (!$newDocument) {
									$binarydata->resetCustomIterator("WHERE filetypecode='".$movieDesc->filetype."' AND elementid='".$value."' AND documentcode='".$this->documentCode."' ");
									$binaryUpdate = ($binaryRow = $binarydata->nextItem()) ? true : false ;
								} else {
									$binaryUpdate = false;
								}
								
								if($binaryUpdate) {
									$fileId = $binaryRow->id;
									$binarydata->addField("id", $fileId);
									
									chmod(CMS_TMP_DIR . $thisFileName, 0644);// bad news.. 
									
									$binarydata->saveItem();
									
									chmod(CMS_TMP_DIR . $thisFileName, 0600);// bad news.. 
								
								} else {
									//if it is a new entry create the new document codes and add to record
									$fileId = $binarydata->db->getId('binarydatatablesequence');
									$binarydata->addField("id", $fileId);
									//write the record.
									
									chmod(CMS_TMP_DIR.$thisFileName, 0644);// bad news.. 
									
									$binarydata->newItem();
									
									chmod(CMS_TMP_DIR.$thisFileName, 0600);// bad news.. 
									
									$query = "Update content set ".$key."=".$fileId." Where documentcode=".$this->documentCode." ";
									$this->db->executeQuery($query);
								}
								
								unlink(CMS_TMP_DIR.$thisFileName);
								
								$started = true;
							}

						}
						
						if (true){//isset($removeFile) && $removeFile) {
							if (file_exists($fileName))
								unlink($fileName);
						}
						clearItemsFromCacheWithDocumentCode($this->documentCode, CMS_BINARY_CACHE_PATH);
					}

				}
				
				//do indexing now
				
				autoIndex($this->documentCode, $this->db);
				
				//add some introspection mojo here perhaps.
				//allow  an array of function names to be passed in that can be called.
			}
			
			// finally
			// if there are no errors..
			// commit all of the changes..
			//otherwise roll back.
			
			if (CMS_WRITER_ENABLE_TRANSACTIONS ){
			
				$commit = false;
				if ($cmsStatusMessage->hasErrors)  {
					//fire a rollback
					$commit = $tableWriter->db->rollback();
				} else {
					//fire a commit
					$commit = $tableWriter->db->commit();
				}
				if (!$commit) {
					$cmsStatusMessage->addValidationMessageForKey("CmsWrite", "db_COMMIT_FAIL", CMS_STATUS_ERROR);
				}
				
				//set the autocommit on the db..
				$this->db->setAutoCommit( true );
			}
			
			//if we have added we need to remove the documentCodeSave so that it doesn't keep using it.
			if($newDocument) {
				$documentCodeSave = null;
				$documentCodeSave = "";
				session_unregister('documentCodeSave');
			}
			
		
			return $cmsStatusMessage;
		}
		
	}

?>